package com.hslxy.niukewang.service;

import com.hslxy.niukewang.util.Constant;
import com.hslxy.niukewang.util.RedisKeyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class FollowService implements Constant {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserService userService;

//    userId是操作用户
    public void follow(int userId, int entityType, int entityId){
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
                String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);
                operations.multi();
//                我关注了什么
                operations.opsForZSet().add(followeeKey, entityId, System.currentTimeMillis());
//                什么实体被我关注了
                operations.opsForZSet().add(followerKey, userId, System.currentTimeMillis());

                return operations.exec();
            }
        });
    }

    //    userId是操作用户
    public void unfollow(int userId, int entityType, int entityId){
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
                String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);
                operations.multi();
//                我关注了什么
                operations.opsForZSet().remove(followeeKey, entityId);
//                什么实体被我关注了
                operations.opsForZSet().remove(followerKey, userId);

                return operations.exec();
            }
        });
    }


//    查询我关注的实体数量
    public long findFolloweeCount(int userId, int entityType){
        String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
        return redisTemplate.opsForZSet().zCard(followeeKey);
    }

//    查询我被关注的数量
    public long findFollowerCount(int entityType, int entityId){
        String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);
        return redisTemplate.opsForZSet().zCard(followerKey);
    }

//    查询关注状态
    public boolean isFollowed(int userId, int entityType, int entityId){
        String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
        return redisTemplate.opsForZSet().score(followeeKey, entityId) != null;
    }

//    查询我关注的人
    public List<Map<String, Object>> findFollowees(int userId, int offset, int limit){
        String followeeKey = RedisKeyUtil.getFolloweeKey(userId, ENTITY_TYPE_USER);
        Set<Integer> set = redisTemplate.opsForZSet().reverseRange(followeeKey, offset, offset + limit - 1);
        if(set == null){
            return null;
        }
        List<Map<String, Object>> list = new ArrayList<>();
        set.stream().forEach((e)->{
            HashMap<String, Object> stringObjectHashMap = new HashMap<>();
            stringObjectHashMap.put("user", userService.findUserById(e));
            Double score = redisTemplate.opsForZSet().score(followeeKey, e);
            stringObjectHashMap.put("followTime", new Date(score.longValue()));
            list.add(stringObjectHashMap);
        });

        return list;
    }

//    查询我被谁关注
    public List<Map<String, Object>>  findFollower(int entityId, int offset, int limit){
        String followerKey = RedisKeyUtil.getFollowerKey(ENTITY_TYPE_USER, entityId);
        Set<Integer> set = redisTemplate.opsForZSet().reverseRange(followerKey, offset, offset + limit - 1);
        if(set == null){
            return null;
        }
        List<Map<String, Object>> list = new ArrayList<>();
        set.stream().forEach((e)->{
            HashMap<String, Object> stringObjectHashMap = new HashMap<>();
            stringObjectHashMap.put("user", userService.findUserById(e));
            Double score = redisTemplate.opsForZSet().score(followerKey, e);
            stringObjectHashMap.put("followTime", new Date(score.longValue()));
            list.add(stringObjectHashMap);
        });
        return list;
    }

}
